import { BadRequestException, HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { Like, Repository } from 'typeorm'
import { formatDate } from 'src/utils'
import { Meeting } from './entities/meeting.entity'
import { CreateMeetingDto } from './dto/create-meeting.dto'
import { UpdateMeetingDto } from './dto/update-meeting.dto'

@Injectable()
export class MeetingService {
  private logger = new Logger()

  @InjectRepository(Meeting)
  private repository: Repository<Meeting>

  initData() {
    const room1 = new Meeting()
    room1.name = '木星'
    room1.capacity = 10
    room1.equipment = '白板'
    room1.location = '一层西'

    const room2 = new Meeting()
    room2.name = '金星'
    room2.capacity = 5
    room2.equipment = ''
    room2.location = '二层东'

    const room3 = new Meeting()
    room3.name = '天王星'
    room3.capacity = 30
    room3.equipment = '白板，电视'
    room3.location = '三层东'

    this.repository.insert([room1, room2, room3])
  }

  async find(pageNo: number, pageSize: number, name: string, capacity: number, equipment: string) {
    // 边界条件检查
    if (pageNo <= 0 || pageSize <= 0) {
      throw new BadRequestException('页码和页数最小为 1')
    }

    const skipCount = (pageNo - 1) * pageSize
    const condition: Record<string, any> = {}
    if (name) {
      condition.name = Like(`%${name}%`)
    }
    if (equipment) {
      condition.equipment = Like(`%${equipment}%`)
    }
    if (capacity) {
      condition.capacity = capacity
    }

    const [meetingRooms, totalCount] = await this.repository.findAndCount({
      skip: skipCount,
      take: pageSize,
      where: condition,
    })

    const rooms = meetingRooms.map((room) => {
      return {
        ...room,
        createTime: formatDate(room.createTime),
        updateTime: formatDate(room.updateTime),
      }
    })

    return {
      meetingRooms: rooms,
      totalCount,
    }
  }

  async create(meetingDto: CreateMeetingDto) {
    try {
      // 原子性: 事务中的所有操作要么全部成功执行，要么全部不执行。如果事务中的任何一步失败，整个事务将回滚，保证数据库状态不变。
      // 隔离性: 多个事务并发执行时，每个事务的操作对其他事务是不可见的，直到事务提交。这可以防止并发操作导致的数据不一致。
      await this.repository.manager.transaction(async (transactionalEntityManager) => {
        const room = await transactionalEntityManager.findOne(Meeting, {
          where: { name: meetingDto.name },
        })

        if (room) {
          throw new BadRequestException('会议室名字已存在')
        }
        const createdRoom = await transactionalEntityManager.save(Meeting, meetingDto)
        return createdRoom
      })
      return '创建成功'
    }
    catch (e) {
      if (e instanceof BadRequestException) {
        // 如果是 BadRequestException，直接抛出
        throw e
      }
      else {
        // 其他错误，记录日志并抛出通用的 HttpException
        this.logger.error(`错误信息: ${e.message}`, MeetingService.name)
        throw new HttpException('创建失败，请稍后再试', HttpStatus.INTERNAL_SERVER_ERROR)
      }
    }
  }

  async update(meetingDto: UpdateMeetingDto) {
    try {
      // 验证 meetingDto.id 是否有效
      if (!meetingDto.id) {
        throw new BadRequestException('无效的会议室 ID')
      }

      const meeting = await this.repository.findOneBy({
        id: meetingDto.id,
      })

      if (!meeting) {
        throw new BadRequestException('会议室不存在')
      }

      const updateMeeting = Object.assign({}, meeting, meetingDto)

      await this.repository.save(updateMeeting)

      return '更新成功'
    }
    catch (e) {
      if (e instanceof BadRequestException) {
        // 如果是 BadRequestException，直接抛出
        throw e
      }
      else {
        // 其他错误，记录日志并抛出通用的 HttpException
        this.logger.error(`错误信息: ${e.message}`, MeetingService.name)
        throw new HttpException('更新失败，请稍后再试', HttpStatus.INTERNAL_SERVER_ERROR)
      }
    }
  }

  async findById(id: number) {
    return this.repository.findOneBy({ id })
  }

  async delete(id: number) {
    try {
      // 输入验证
      if (!id || id <= 0) {
        throw new BadRequestException('无效的id')
      }

      await this.repository.delete({ id })
      return '删除成功'
    }
    catch (e) {
      if (e instanceof BadRequestException) {
        // 如果是 BadRequestException，直接抛出
        throw e
      }
      else {
        // 其他错误，记录日志并抛出通用的 HttpException
        this.logger.error(`错误信息: ${e.message}`, MeetingService.name)
        throw new HttpException('删除失败，请稍后再试', HttpStatus.INTERNAL_SERVER_ERROR)
      }
    }
  }
}
